package com.wno704.quartz.service.impl;


import com.wno704.quartz.entity.Job;
import com.wno704.quartz.config.WnoConfig;
import com.wno704.quartz.service.JobService;
import com.wno704.quartz.util.ScheduleUtils;

import lombok.RequiredArgsConstructor;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.Arrays;
import java.util.List;

/**
 * Job实现类
 * <p>
 * Author: wwno704
 */
@Service("JobService")
@RequiredArgsConstructor
public class JobServiceImpl implements JobService {

    private final Scheduler scheduler;

    @Autowired
    @Qualifier("jdbcTemplateQuartz")
    private JdbcTemplate jdbcTemplateQuartz;

    @Autowired
    WnoConfig wnoConfig;

    @PostConstruct
    @Override
    public int init() {
        String sql = null;

        if (wnoConfig.getQuartzDB().equals("MySQL")) {
            sql = "SELECT T.JOB_ID,T.BEAN_NAME,T.METHOD_NAME,T.PARAMS,T.CRON_EXPRESSION,DATE_FORMAT(T.START_TIME,'%Y-%m-%d %H:%i:%s') START_TIME,DATE_FORMAT(T.END_TIME,'%Y-%m-%d %H:%i:%s') END_TIME,T.STATUS,T.REMARK,DATE_FORMAT(T.CREATE_TIME,'%Y-%m-%d %H:%i:%s') CREATE_TIME,T.TRANS_TYPE FROM QRTZ_JOB T WHERE T.UPDATE_STATUS = '0' ";
        }
        if (wnoConfig.getQuartzDB().equals("Oracle") || wnoConfig.getQuartzDB().equals("PostgreSQL")) {
            sql = "SELECT T.JOB_ID,T.BEAN_NAME,T.METHOD_NAME,T.PARAMS,T.CRON_EXPRESSION,TO_CHAR(T.START_TIME,'YYYY-MM-DD HH24:MI:SS') START_TIME,TO_CHAR(T.END_TIME,'YYYY-MM-DD HH24:MI:SS') END_TIME,T.STATUS,T.REMARK,TO_CHAR(T.CREATE_TIME,'YYYY-MM-DD HH24:MI:SS') CREATE_TIME,T.TRANS_TYPE FROM QRTZ_JOB T WHERE T.UPDATE_STATUS = '0' ";
        }

        List<Job> scheduleJobList = this.jdbcTemplateQuartz.query(sql, new BeanPropertyRowMapper<Job>(Job.class));

        scheduleJobList.forEach(scheduleJob -> {
            CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobId());
            if (cronTrigger == null) {
                ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
            } else {
                ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
            }
            String upSql = "UPDATE QRTZ_JOB  SET UPDATE_STATUS = '1' WHERE JOB_ID = ? ";
            this.jdbcTemplateQuartz.update(upSql, new Object[]{scheduleJob.getJobId()});
        });
        return scheduleJobList.size();
    }

    @Override
    public Job findJob(Long jobId) {
        // TODO Auto-generated method stub
        String sql = null;

        if (wnoConfig.getQuartzDB().equals("MySQL")) {
            sql = "SELECT T.JOB_ID,T.BEAN_NAME,T.METHOD_NAME,T.PARAMS,T.CRON_EXPRESSION,DATE_FORMAT(T.START_TIME,'%Y-%m-%d %H:%i:%s') START_TIME,DATE_FORMAT(T.END_TIME,'%Y-%m-%d %H:%i:%s') END_TIME,T.STATUS,T.REMARK,DATE_FORMAT(T.CREATE_TIME,'%Y-%m-%d %H:%i:%s') CREATE_TIME," +
                    "T.TRANS_TYPE,T.TEMPLATE_SRC_NAME,T.TEMPLATE_DST_NAME,T.SRC_COMMD,T.DST_COMMD,T.TEMPLATE_DST_TWO_NAME,T.DST_TWO_COMMD FROM QRTZ_JOB T WHERE T.JOB_ID = ? ";
        }
        if (wnoConfig.getQuartzDB().equals("Oracle") || wnoConfig.getQuartzDB().equals("PostgreSQL")) {
            sql = "SELECT T.JOB_ID,T.BEAN_NAME,T.METHOD_NAME,T.PARAMS,T.CRON_EXPRESSION,TO_CHAR(T.START_TIME,'YYYY-MM-DD HH24:MI:SS') START_TIME,TO_CHAR(T.END_TIME,'YYYY-MM-DD HH24:MI:SS') END_TIME,T.STATUS,T.REMARK,TO_CHAR(T.CREATE_TIME,'YYYY-MM-DD HH24:MI:SS') CREATE_TIME," +
                    "T.TRANS_TYPE,T.TEMPLATE_SRC_NAME,T.TEMPLATE_DST_NAME,T.SRC_COMMD,T.DST_COMMD,T.TEMPLATE_DST_TWO_NAME,T.DST_TWO_COMMD FROM QRTZ_JOB T WHERE T.JOB_ID = ? ";
        }

        List<Job> scheduleJobList = this.jdbcTemplateQuartz.query(sql, new Object[]{jobId}, new BeanPropertyRowMapper<Job>(Job.class));
        return scheduleJobList.get(0);
    }

    @Override
    public void createJob(Job job) {
        // TODO Auto-generated method stub
        String insertSql = "insert QRTZ_JOB  WHERE JOB_ID = ? ";
        long jobid = this.jdbcTemplateQuartz.update(insertSql, new Object[]{job.getJobId()});
        job.setJobId(jobid);
        ScheduleUtils.createScheduleJob(scheduler,job);
    }

    @Override
    public void updateJob(Job job) {
        // TODO Auto-generated method stub
        String upSql = "UPDATE QRTZ_JOB  SET UPDATE_STATUS = ? WHERE JOB_ID = ? ";
        this.jdbcTemplateQuartz.update(upSql, new Object[]{job.getJobId()});
        ScheduleUtils.updateScheduleJob(scheduler, job);
    }

    @Override
    public void deleteJobs(String[] jobIds) {
        // TODO Auto-generated method stub
        String delSql = "DELETE QRTZ_JOB  WHERE JOB_ID = ? ";
        for (String jobId: jobIds) {
            ScheduleUtils.deleteScheduleJob(scheduler,Long.valueOf(jobId));
            this.jdbcTemplateQuartz.update(delSql, new Object[]{Long.valueOf(jobId)});
        }
    }

    @Override
    public void updateBatch(String jobIds, String status) {
        // TODO Auto-generated method stub
        String upSql = "UPDATE QRTZ_JOB  SET UPDATE_STATUS = ? WHERE JOB_ID = ? ";
        String[] list = jobIds.split(",");
        Arrays.stream(list).forEach(jobId -> {
            this.jdbcTemplateQuartz.update(upSql, new Object[]{status,Long.valueOf(jobId)});
            Job scheduleJob = this.findJob(Long.valueOf(jobId));
            scheduleJob.setStatus(status);
            ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
        });
    }

    @Override
    public void run(String jobIds) {
        // TODO Auto-generated method stub
        String[] list = jobIds.split(",");
        Arrays.stream(list).forEach(jobId -> {
            ScheduleUtils.run(scheduler, this.findJob(Long.valueOf(jobId)));
        });
    }

    @Override
    public void pause(String jobIds) {
        // TODO Auto-generated method stub
        String[] list = jobIds.split(",");
        Arrays.stream(list).forEach(jobId -> {
            ScheduleUtils.pauseJob(scheduler, Long.valueOf(jobId));
        });
    }

    @Override
    public void resume(String jobIds) {
        // TODO Auto-generated method stub
        String[] list = jobIds.split(",");
        Arrays.stream(list).forEach(jobId -> {
            ScheduleUtils.resumeJob(scheduler, Long.valueOf(jobId));
        });
    }

}
